package com.faxsun.core.catalog.domain;

import com.faxsun.common.currency.domain.FSCurrencyEnum;
import com.faxsun.core.pricing.service.fulfillment.calculator.ShippmentFeeCalculator;
import org.broadleafcommerce.common.currency.domain.BroadleafCurrency;
import org.broadleafcommerce.common.currency.domain.BroadleafCurrencyImpl;
import org.broadleafcommerce.common.money.Money;
import org.broadleafcommerce.common.presentation.AdminPresentation;
import org.broadleafcommerce.common.presentation.AdminPresentationToOneLookup;
import org.broadleafcommerce.common.presentation.RequiredOverride;
import org.broadleafcommerce.common.presentation.client.SupportedFieldType;
import org.broadleafcommerce.common.presentation.client.VisibilityEnum;
import org.broadleafcommerce.core.catalog.domain.ProductImpl;
import org.broadleafcommerce.core.catalog.domain.ProductImpl.Presentation;
import org.broadleafcommerce.core.catalog.domain.SkuImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.persistence.*;
import java.math.BigDecimal;

@Entity
@Table(name = "FS_SKU")
@Inheritance(strategy = InheritanceType.JOINED)
@Component
public class FSSkuImpl extends SkuImpl implements FSSku {

    /**
     *
     */
    private static final long serialVersionUID = -1851477399386690306L;

    @ManyToOne(optional = false, targetEntity = BroadleafCurrencyImpl.class)
    @JoinColumn(name = "CURRENCY_CODE", unique = false, nullable = false)
    @AdminPresentation(friendlyName = "SkuImpl_Sku_Price_Currency", order = 2000, group = ProductImpl.Presentation.Group.Name.Price, groupOrder = ProductImpl.Presentation.Group.Order.Price, fieldType = SupportedFieldType.BROADLEAF_ENUMERATION, broadleafEnumeration = "com.faxsun.common.currency.domain.FSCurrencyEnum", requiredOverride = RequiredOverride.REQUIRED)
    @AdminPresentationToOneLookup(lookupDisplayProperty = "friendlyName")
    protected BroadleafCurrency priceCurrency;

    @Column(name = "FOREIGN_PRICE", nullable = false)
    @AdminPresentation(friendlyName = "SkuImpl_Sku_Price_Foreign", group = ProductImpl.Presentation.Group.Name.Price, order = 2000, fieldType = SupportedFieldType.MONEY, groupOrder = ProductImpl.Presentation.Group.Order.Price)
    protected BigDecimal foreignPrice;

    @Column(name = "DESCRIPTION")
    @AdminPresentation(friendlyName = "SkuImpl_Sku_Description", order = ProductImpl.Presentation.FieldOrder.SHORT_DESCRIPTION, group = ProductImpl.Presentation.Group.Name.General, groupOrder = ProductImpl.Presentation.Group.Order.General, largeEntry = true, translatable = true)
    protected String shortDescription;

    @Column(name = "KEYWORDS")
    @AdminPresentation(friendlyName = "SkuImpl_Sku_Keywords", order = ProductImpl.Presentation.FieldOrder.SHORT_DESCRIPTION, group = ProductImpl.Presentation.Group.Name.General, groupOrder = ProductImpl.Presentation.Group.Order.General, largeEntry = true, translatable = true)
    protected String keywords;

    @Column(name = "SHIPPING_FEE")
    @AdminPresentation(friendlyName = "ProductImpl_Product_ShippingFee", order = 1100, group = Presentation.Group.Name.Shipping, groupOrder = Presentation.Group.Order.General, requiredOverride = RequiredOverride.NOT_REQUIRED)
    protected BigDecimal shippingFee;

    @Column(name = "QUANTITY_AVAILABLE")
    @AdminPresentation(friendlyName = "SkuImpl_Sku_QuantityAvailable", order = 1010, tab = ProductImpl.Presentation.Tab.Name.Inventory, tabOrder = ProductImpl.Presentation.Tab.Order.Inventory, group = ProductImpl.Presentation.Group.Name.Inventory, groupOrder = ProductImpl.Presentation.Group.Order.Inventory)
    protected Integer quantityAvailable = 0;

    @Column(name = "QUANTITY_TOTAL")
    @AdminPresentation(friendlyName = "SkuImpl_Sku_QuantityTotal", order = 1001, tab = ProductImpl.Presentation.Tab.Name.Inventory, tabOrder = ProductImpl.Presentation.Tab.Order.Inventory, group = ProductImpl.Presentation.Group.Name.Inventory, groupOrder = ProductImpl.Presentation.Group.Order.Inventory)
    protected Integer quantityTotal = 0;

    @Column(name = "MARKET_PRICE", precision = 19, scale = 5)
    @AdminPresentation(friendlyName = "SkuImpl_Sku_Market_Price", order = 1000, group = ProductImpl.Presentation.Group.Name.Price, groupOrder = ProductImpl.Presentation.Group.Order.Price, fieldType = SupportedFieldType.MONEY)
    protected BigDecimal marketPrice;

    @Column(name = "LOWER_LIMIT")
    @AdminPresentation(friendlyName = "SkuImpl_Sku_GroupBuyLowerLimit", order = 2000, tab = ProductImpl.Presentation.Tab.Name.Inventory,
        tabOrder = ProductImpl.Presentation.Tab.Order.Inventory, group = ProductImpl.Presentation.Group.Name.Inventory,
        groupOrder = ProductImpl.Presentation.Group.Order.Inventory)
    protected Integer groupBuyLowerLimit;

    @Column(name = "SKU_STATUS")
    @AdminPresentation(friendlyName = "FSSkuImpl_Sku_Status", group = Presentation.Group.Name.General, order = 7000, prominent = true, fieldType = SupportedFieldType.BROADLEAF_ENUMERATION, broadleafEnumeration = "com.faxsun.admin.service.type.FSSkuStatus", groupOrder = Presentation.Group.Order.General, visibility = VisibilityEnum.NOT_SPECIFIED, requiredOverride = RequiredOverride.REQUIRED)
    protected String skuStatus;

    @Transient
    private static ShippmentFeeCalculator feeCalculator;

    public FSCurrencyEnum getPriceCurrency() {
        return FSCurrencyEnum.getInstance(priceCurrency.getCurrencyCode());
    }

    public void setPriceCurrency(FSCurrencyEnum priceCurrency) {
        this.priceCurrency = priceCurrency.getBroadleafCurrency();
    }

    public Money getForeignPrice() {
        if (this.priceCurrency != null) {
            return new Money(foreignPrice, priceCurrency);
        }
        return new Money(foreignPrice);
    }

    public void setForeignPrice(Money foreignPrice) {
        this.foreignPrice = Money.toAmount(foreignPrice);
    }

    /**
     * 获取汇率对应的BroadleafCurrency类型
     *
     * @return
     */
    public BroadleafCurrency getPriceBroadleafCurrency() {
        return this.priceCurrency;
    }

    @Override
    public Money getOriginRetailPrice() {
        return new Money(this.retailPrice);
    }

    public String getShortDescription() {
        return shortDescription;
    }

    public void setShortDescription(String shortDescription) {
        this.shortDescription = shortDescription;
    }

    public BigDecimal getShippingFee() {
        return shippingFee;
    }

    public void setShippingFee(BigDecimal shippingFee) {
        this.shippingFee = shippingFee;
    }

    public Integer getQuantityAvailable() {
        return quantityAvailable;
    }

    public void setQuantityAvailable(Integer quantityAvailable) {
        this.quantityAvailable = quantityAvailable;
    }

    public Integer getQuantityTotal() {
        return quantityTotal;
    }

    public void setQuantityTotal(Integer quantityTotal) {
        this.quantityTotal = quantityTotal;
    }

    public Money getMarketPrice() {
        if (marketPrice == null) {
            return null;
        }
        return new Money(marketPrice);
    }

    public void setMarketPrice(Money marketPrice) {
        this.marketPrice = marketPrice.getAmount();
    }

    /**
     * sku运费
     *
     * @return
     */
    public Money getCalculatedShippmentFee() {
        return feeCalculator.calculateShippmentFeeBySku(this, 1);
    }

    /**
     * 获取显示价格，售价+运费 新需求：界面显示售价为实际售价+运费
     *
     * @return 售价+运费
     */
    public Money getDisplayedTotalPrice() {
        return this.getPrice().add(getCalculatedShippmentFee());
    }

    public ShippmentFeeCalculator getFeeCalculator() {
        return feeCalculator;
    }

    @Autowired
    public void setFeeCalculator(ShippmentFeeCalculator feeCalculator) {
        FSSkuImpl.feeCalculator = feeCalculator;
    }

    @PostConstruct
    public void init() {
        getFeeCalculator();
    }

    public String getKeywords() {
        return keywords;
    }

    public void setKeywords(String keywords) {
        this.keywords = keywords;
    }

    public Integer getGroupBuyLowerLimit() {
        return groupBuyLowerLimit;
    }

    public void setGroupBuyLowerLimit(Integer groupBuyLowerLimit) {
        this.groupBuyLowerLimit = groupBuyLowerLimit;
    }

    public String getSkuStatus() {
        return skuStatus;
    }

    public void setSkuStatus(String skuStatus) {
        this.skuStatus = skuStatus;
    }

}